package tools;

public class DoubleArray
{
	/**
	 * Returns the transpose of a Double [][] array seen as a matrix.
	 */
	public static Double [][] transpose(Double [][] arr)
	{
		int na = arr.length ;
		int nb = arr[0].length ;
		Double [][] tarr = new Double[nb][na] ;
		for(int ii=0 ; ii<na ; ii++)
			for(int jj=0 ; jj<nb ; jj++)
				tarr[jj][ii] = arr[ii][jj] ;
		
		return tarr ;
	}
	
	/**
	 * Get specified column of a Double [][] array
	 */
	public static Double [] getColumn(Double [][] arr, int dacol)
	{
		int numrows = arr.length ;
		int numcols = arr[0].length ;
		
		Double [] ret = new Double[numrows] ;
		for(int ii=0 ; ii<numrows ; ii++)
			ret[ii] = arr[ii][dacol] ;
		
		return ret ;
	}
	
	/**
	 * Cosine between two vectors
	 */
	public static double cosine(Double [] x, Double [] y)
	{
		return dotprod(x,y)/(eucnorm(x)*eucnorm(y)) ;
	}
	
	/**
	 * Dot product between two vectors
	 */
	public static double dotprod(Double [] x, Double [] y)
	{
		double dp = 0 ;
		for(int i=0 ; i<x.length ; i++)
			dp = dp + x[i]*y[i] ;
		return dp ;
	}
	
	/**
	 * Euclidean norm of input vector
	 */
	public static double eucnorm(Double [] x)
	{
		double nn = 0 ;
		for(int i=0 ; i<x.length ; i++)
			nn = nn + x[i]*x[i] ;
		return Math.sqrt(nn) ;
	}
	
	public static Double [] Normalize1stdim1(Double [] t)
	{
		int n1 = t.length ;
		double dasum = 0 ;
		
		for(int ii=0; ii<n1; ii++) dasum = dasum + t[ii] ;

		if(dasum == 0) {dasum = 1e-12 ; }
		
		for(int ii=0 ; ii<n1; ii++) t[ii] = t[ii] / dasum ;

		return t ;
	}
	
	
	public static Double [][] Normalize1stdim2(Double [][] t)
	{
		int n1 = t.length ;
		int n2 = t[0].length ;

		for(int jj=0  ; jj < n2 ; jj++)
		{
			double dasum = 0 ;
			for(int ii=0 ; ii < n1 ; ii++)
				dasum = dasum + t[ii][jj] ;
			
			if(dasum == 0)
				{dasum = 1e-12 ;
			}
			for(int ii=0 ; ii < n1 ; ii++)
				t[ii][jj] = t[ii][jj] / dasum ;
		}
		
		return t ;
	}
	
	/** Normalize an array of doubles so that it sums to 1.
	 *  Returns a copy of the array.
	 * 
	 */
	public static Double [] NormalizeSum(Double [] t)
	{
		double ss = 0 ;
		Double [] t2 = new Double[t.length] ;
		for(int i=0 ; i<t.length ; i++) ss = ss + t[i] ;
		if(ss == 0) ss = 1e-6 ;
		for(int i=0 ; i<t.length ; i++) t2[i] = t[i] / ss ;
		return t2 ;
	}
	
	/**
	 * Get a random uniform distribution of given length.
	 * (sums to 1).
	 */
	public static double [] getRandomDistribution(int length)
	{
		double [] randp =  new double[length] ; double sumrandp=0 ;
		for(int j=0 ; j<length; j++)
			{randp[j] = Math.random() ; sumrandp=sumrandp+randp[j] ;}
		for(int j=0 ; j<length; j++) randp[j] = randp[j] / sumrandp ;
		return randp ;
	}
	
	/**
	 * Returns index of the maximum element in input array
	 */
	public static int getMaxIndex(Double [] t)
	{
		int daind=0 ;

		for(int i=0 ; i<t.length; i++)
			if(t[i] > t[daind])
				daind = i ;
		
		return daind ;
	}
	
	/**
	 * Returns a integer array corresponding to indices of
	 * the value of the input when sorted in descending order
	 * (dirty pig quadratic version).
	 */
	public static int [] getIndicesDescending(Double [] t)
	{
		// copy t
		Double [] ct = new Double[t.length] ;
		for(int i=0 ; i<t.length; i++) ct[i] = t[i] ;
		
		int [] ret = new int[ct.length] ;
		for(int ii=0 ; ii<ct.length ; ii++)
		{
			int daind = getMaxIndex(ct) ;
			ret[ii] = daind ;
			ct[daind] = Double.NEGATIVE_INFINITY ;
 		}
		
		return ret ;
	}
	
	/**
	 * Returns the transpose of a double [][] array seen as a matrix.
	 */
	public static double [][] transpose(double [][] arr)
	{
		int na = arr.length ;
		int nb = arr[0].length ;
		double [][] tarr = new double[nb][na] ;
		for(int ii=0 ; ii<na ; ii++)
			for(int jj=0 ; jj<nb ; jj++)
				tarr[jj][ii] = arr[ii][jj] ;
		
		return tarr ;
	}
	
	/**
	 * Get specified column of a double [][] array
	 */
	public static double [] getColumn(double [][] arr, int dacol)
	{
		int numrows = arr.length ;
		int numcols = arr[0].length ;
		
		double [] ret = new double[numrows] ;
		for(int ii=0 ; ii<numrows ; ii++)
			ret[ii] = arr[ii][dacol] ;
		
		return ret ;
	}
	
	/**
	 * Cosine between two vectors
	 */
	public static double cosine(double [] x, double [] y)
	{
		return dotprod(x,y)/(eucnorm(x)*eucnorm(y)) ;
	}
	
	/**
	 * Dot product between two vectors
	 */
	public static double dotprod(double [] x, double [] y)
	{
		double dp = 0 ;
		for(int i=0 ; i<x.length ; i++)
			dp = dp + x[i]*y[i] ;
		return dp ;
	}
	
	/**
	 * Euclidean norm of input vector
	 */
	public static double eucnorm(double [] x)
	{
		double nn = 0 ;
		for(int i=0 ; i<x.length ; i++)
			nn = nn + x[i]*x[i] ;
		return Math.sqrt(nn) ;
	}
	
	public static double [] Normalize1stdim1(double [] t)
	{
		int n1 = t.length ;
		double dasum = 0 ;
		
		for(int ii=0; ii<n1; ii++) dasum = dasum + t[ii] ;

		if(dasum == 0) {dasum = 1e-12 ; }
		
		for(int ii=0 ; ii<n1; ii++) t[ii] = t[ii] / dasum ;

		return t ;
	}
	
	
	public static double [][] Normalize1stdim2(double [][] t)
	{
		int n1 = t.length ;
		int n2 = t[0].length ;

		for(int jj=0  ; jj < n2 ; jj++)
		{
			double dasum = 0 ;
			for(int ii=0 ; ii < n1 ; ii++)
				dasum = dasum + t[ii][jj] ;
			
			if(dasum == 0)
				{dasum = 1e-12 ;
			}
			for(int ii=0 ; ii < n1 ; ii++)
				t[ii][jj] = t[ii][jj] / dasum ;
		}
		
		return t ;
	}
	
	/** Normalize an array of doubles so that it sums to 1.
	 *  Returns a copy of the array.
	 * 
	 */
	public static double [] NormalizeSum(double [] t)
	{
		double ss = 0 ;
		double [] t2 = new double[t.length] ;
		for(int i=0 ; i<t.length ; i++) ss = ss + t[i] ;
		if(ss == 0) ss = 1e-6 ;
		for(int i=0 ; i<t.length ; i++) t2[i] = t[i] / ss ;
		return t2 ;
	}

	/**
	 * Returns index of the maximum element in input array
	 */
	public static int getMaxIndex(double [] t)
	{
		int daind=0 ;

		for(int i=0 ; i<t.length; i++)
			if(t[i] > t[daind])
				daind = i ;
		
		return daind ;
	}
	
	/**
	 * Returns a integer array corresponding to indices of
	 * the value of the input when sorted in descending order
	 * (dirty pig quadratic version).
	 */
	public static int [] getIndicesDescending(double [] t)
	{
		// copy t
		double [] ct = new double[t.length] ;
		for(int i=0 ; i<t.length; i++) ct[i] = t[i] ;
		
		int [] ret = new int[ct.length] ;
		for(int ii=0 ; ii<ct.length ; ii++)
		{
			int daind = getMaxIndex(ct) ;
			ret[ii] = daind ;
			ct[daind] = Double.NEGATIVE_INFINITY ;
 		}
		
		return ret ;
	}
	
	
}
